package rbac

import (
	"context"
	"gitee.com/bobo-rs/creative-framework/pkg/utils"
	"gitee.com/bobo-rs/innovideo-services/enums"
	"gitee.com/bobo-rs/innovideo-services/framework/dao"
	"gitee.com/bobo-rs/innovideo-services/framework/model"
	"gitee.com/bobo-rs/innovideo-services/framework/model/entity"
	"gitee.com/bobo-rs/innovideo-services/library/exception"
	"github.com/gogf/gf/v2/frame/g"
)

// SavePermAssoc 保存关联权限数据
func (r *sRbac) SavePermAssoc(ctx context.Context, assocId uint, assocType enums.PermAssocType, permId ...uint) error {
	if len(permId) == 0 {
		return exception.New(`缺少权限ID`)
	}

	// 迭代处理数据
	adds := make([]entity.PermissonsAssoc, 0)
	for _, pid := range permId {
		adds = append(adds, entity.PermissonsAssoc{
			PermissionsId: pid,
			AssocType:     uint(assocType),
			AssocId:       assocId,
		})
	}

	// 移除数据
	_, _ = dao.PermissonsAssoc.Ctx(ctx).
		Where(dao.PermissonsAssoc.Columns().AssocId, assocId).
		Where(dao.PermissonsAssoc.Columns().AssocType, assocType).
		Delete()

	// 保存数据
	_, err := dao.PermissonsAssoc.Ctx(ctx).Save(adds)
	if err != nil {
		return exception.New(`关联权限保存失败`)
	}

	return nil
}

// RemovePermAssocByPmId 权限删除或禁用移除关联
func (r *sRbac) RemovePermAssocByPmId(ctx context.Context, pmId uint) error {
	if pmId == 0 {
		return exception.New(`权限ID不能为0`)
	}
	_, err := dao.PermissonsAssoc.Ctx(ctx).
		Where(dao.PermissonsAssoc.Columns().PermissionsId, pmId).
		Delete()
	if err != nil {
		return exception.New(`删除绑定失败或已删除`)
	}
	return nil
}

// RemovePermAssocByAssocId 通过关联ID解除权限关联
func (r *sRbac) RemovePermAssocByAssocId(ctx context.Context, assocType enums.PermAssocType, assocId ...uint) error {
	if len(assocId) == 0 {
		return exception.Newf(`缺少%sID`, assocType.Fmt())
	}
	// 检测是否绑定权限
	b, _ := r.AssocModel().Exists(ctx, g.Map{
		dao.PermissonsAssoc.Columns().AssocId:   assocId,
		dao.PermissonsAssoc.Columns().AssocType: assocType,
	})
	if b == false {
		return nil
	}

	// 解除关联
	_, err := dao.PermissonsAssoc.Ctx(ctx).
		Where(dao.PermissonsAssoc.Columns().AssocId, assocId).
		Where(dao.PermissonsAssoc.Columns().AssocType, assocType).
		Delete()
	if err != nil {
		return exception.Newf(`解除%s关联权限失败`, assocType.Fmt())
	}
	return nil
}

// GetPermissionsIdByRoleId 通过角色ID-获取权限ID集合
func (r *sRbac) GetPermissionsIdByRoleId(ctx context.Context, roleId ...uint) ([]uint, error) {
	// 获取权限ID集合
	return r.GetPermissionsIdByAssocId(ctx, enums.PermAssocTypeRoles, roleId...)
}

// GetPermissionsIdByAdminId 通过管理员ID-获取权限ID集合
func (r *sRbac) GetPermissionsIdByAdminId(ctx context.Context, adminId uint) ([]uint, error) {
	// 获取权限ID
	return r.GetPermissionsIdByAssocId(ctx, enums.PermAssocTypeUser, adminId)
}

// GetPermissionsIdByAssocId 通过关联ID和类型获取权限ID集合
func (r *sRbac) GetPermissionsIdByAssocId(ctx context.Context, assocType enums.PermAssocType, assocId ...uint) ([]uint, error) {
	if len(assocId) == 0 {
		return nil, exception.Newf(`缺少%sId`, assocType.Fmt())
	}

	var permIdArr []model.PermAssocPermId
	err := r.AssocModel().Scan(ctx, g.Map{
		dao.PermissonsAssoc.Columns().AssocId:   assocId,
		dao.PermissonsAssoc.Columns().AssocType: assocType,
	}, &permIdArr)
	if err != nil {
		return nil, exception.New(`暂无数据`)
	}

	// 转换权限ID集合
	return utils.NewArray(permIdArr).Units(dao.PermissonsAssoc.Columns().PermissionsId), nil
}
